package orz.itrip.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import orz.itrip.DtoUtils;
import orz.itrip.MD5Utils;
import orz.itrip.UUIDUtils;
import orz.itrip.auth.service.UserService;
import orz.itrip.auth.vo.PhoneApi;
import orz.itrip.dto.Dto;
import orz.itrip.mapper.UserMapper;
import orz.itrip.pojo.User;
import orz.itrip.vo.ItripToken;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private JavaMailSender javaMailSender;

    @Resource
    private SimpleMailMessage simpleMailMessage;

    @Resource
    private PhoneApi phoneApi;
    @Override
    public Dto isExists(String name) {
        User user = new User();
        user.setUserCode(name);
        boolean b = userMapper.selectCount(user) == 0;
        if (!b){
            return DtoUtils.getFalseDto("已经存在此用户","10002");
        }else {
            return DtoUtils.getSuccessDto("可以注册");
        }
    }

    @Override
    public Dto regedit(User user) throws MessagingException {

        //1、先添加 未激活状态
        user.setActivated(0);
        user.setCreationDate(new Date());
        user.setModifyDate(new Date());
        //密码加密
        user.setUserPassword(MD5Utils.encodeStr(user.getUserPassword()));
        if (!(userMapper.insert(user)>0)){
            return DtoUtils.getFalseDto("添加失败，联系管理员","10001");
        }
        //2、生成验证码   UUID/GUID
        String code = UUIDUtils.getStr();
        //3、保存验证码到redis
        stringRedisTemplate.opsForValue().set(user.getUserCode(),code,24*60, TimeUnit.MINUTES);
        //4、发送邮件
        simpleMailMessage.setText("欢迎注册我们网站，您的验证码是"+code+",一天内有效，尽快激活");
        simpleMailMessage.setSubject("爱旅行网站标题");
        simpleMailMessage.setTo(user.getUserCode());
        javaMailSender.send(simpleMailMessage);
        return DtoUtils.getSuccessDto("消息发送成功");
    }

    @Override
    public Dto activeUser(String user, String code) {
        //1、是否存在用户
        if (!stringRedisTemplate.hasKey(user)){
            return DtoUtils.getFalseDto("用户不存在或者已经激活","10003");
        }
        if (StringUtils.isEmpty(code)){
            return DtoUtils.getFalseDto("验证码不为空","10004");
        }
        //2、看验证码是否一致
        if(!stringRedisTemplate.opsForValue().get(user).equals(code)){
            return DtoUtils.getFalseDto("验证码不匹配","10005");
        }
        User user1 = new User();
        user1.setUserCode(user);
        User yh = userMapper.selectOne(user1);
        yh.setActivated(1);
        //3、修改用户激活状态
        userMapper.updateByPrimaryKey(yh);
        //4、删除redis的code
        stringRedisTemplate.delete(user);
        //5、给用户相应
        return DtoUtils.getSuccessDto("激活成功");
    }

    @Override
    public Dto regeditByphone(User user) {
        // 1 先添加 未激活状态
        user.setCreationDate(new Date());
        user.setModifyDate(new Date());
        user.setActivated(0);
        //密码需要加密
        user.setUserPassword(MD5Utils.encodeStr(user.getUserPassword()));
        if (!(userMapper.insert(user)>0)) {
            return DtoUtils.getFalseDto("添加失败，联系管理员","10001");
        }
        //2 生成验证码  UID 3000年  32  48 36   4 位随机数
        Random random=new Random();
        String code= random.nextInt(10)+""+random.nextInt(10)+random.nextInt(10)+random.nextInt(10);
        //3 保存验证码到redis
        stringRedisTemplate.opsForValue().set(user.getUserCode(),code,5, TimeUnit.MINUTES);
        //4 发送短信
        phoneApi.sendTemplateSMS(user.getUserCode(),"1" ,new String[]{code,1+""});

        return DtoUtils.getSuccessDto("消息发送成功");
    }

    @Override
    public Dto<ItripToken> selectByLogin(String name, String password,String from) {
        User t = new User();
        t.setUserCode(name);
        t.setUserPassword(MD5Utils.encodeStr(password));
        t = userMapper.selectOne(t);
        //判断数据是否可以登录
        if (ObjectUtils.isEmpty(t)){
            return DtoUtils.getFalseDto("用户密码不匹配","10006");
        }
        if (t.getActivated() == 0){
            return DtoUtils.getFalseDto("用户未激活","10007");
        }
        ItripToken itripToken = buildToken(from, t);

        return DtoUtils.getSuccesWithData(itripToken,"登录成功");
    }

    /**
     * 生成token并保存到redis数据库中
     * @param from
     * @param t
     * @return
     */
    private ItripToken buildToken(String from, User t) {
        //生成一个token，保存到redis,将token的结果返回给前端
        //规则 ： 请求来源 - 用户编码 - 用户ID - 随机六位 - 时间
        Date date = new Date();
        int time = 30;
        if (!from.equals("pc")){
            time = Integer.MAX_VALUE;
        }
        String token = "token:"+from+"-"+ MD5Utils.encodeStr(t.getUserCode())+"-"+t.getId()+"-"+ UUIDUtils.getStr(6,false)+"-"+getTimeStr(date);

        stringRedisTemplate.opsForValue().set(token, JSON.toJSONString(t),time, TimeUnit.MINUTES);

        ItripToken itripToken = new ItripToken();
        itripToken.setToken(token);
        itripToken.setGenTime(date.getTime());
        itripToken.setExpTime(date.getTime()+time*60*1000);
        return itripToken;
    }

    @Override
    public Dto logout(String token) {
        //判断登录信息是否有效
        if (StringUtils.isEmpty(token)){
            return DtoUtils.getFalseDto("都没有登录，注什么注","10009");
        }
        //判断token是否与redis中一致
        if (!stringRedisTemplate.hasKey(token)){
            return DtoUtils.getFalseDto("都没有登录，注什么注","10009");
        }
        //根据从redis中取出的token进行删除操作
        stringRedisTemplate.delete(token);
        return DtoUtils.getSuccessDto("注销成功");
    }

    @Override
    public Dto<ItripToken> retoken(String token) {
        if (!stringRedisTemplate.hasKey(token)){
            return DtoUtils.getFalseDto("都没有登录，换什么换","10009");
        }
        String from = "pc";
        //判断登录平台，如果为移动端登录则无需重置token时间
        if (!token.startsWith("token:pc")){
            return DtoUtils.getFalseDto("离过期还早着呢","10011");
        }
        String userJson = stringRedisTemplate.opsForValue().get(token);
        String dateTime = token.substring(token.lastIndexOf("-")+1);
        long time = getTime(dateTime);
        if (new Date().getTime()-time<25*60*1000){
            return DtoUtils.getFalseDto("离过期还早着呢","10011");
        }
        //1、将老的token的时间重新计时
//        stringRedisTemplate.expire(token,30,TimeUnit.MINUTES);
        //2、删除老token，创建新token
        ItripToken itripToken = buildToken(from, JSONObject.parseObject(userJson,User.class));
        return DtoUtils.getSuccesWithData(itripToken,"retoken成功");
    }

    private long getTime(String dateTime) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            return simpleDateFormat.parse(dateTime).getTime();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    private String getTimeStr(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return simpleDateFormat.format(date);
    }

}
